{
 "cells": [
  {
   "cell_type": "raw",
   "id": "af408f61",
   "metadata": {},
   "source": [
    "---\n",
    "sidebar_position: 1\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a65e4c9",
   "metadata": {},
   "source": [
    "# How to use example selectors\n",
    "\n",
    ":::info Prerequisites\n",
    "\n",
    "This guide assumes familiarity with the following concepts:\n",
    "\n",
    "- [Prompt templates](/docs/concepts/#prompt-templates)\n",
    "- [Few-shot examples](/docs/how_to/few_shot_examples)\n",
    "\n",
    ":::\n",
    "\n",
    "If you have a large number of examples, you may need to select which ones to include in the prompt. The Example Selector is the class responsible for doing so.\n",
    "\n",
    "The base interface is defined as below:\n",
    "\n",
    "```typescript\n",
    "class BaseExampleSelector {\n",
    "  addExample(example: Example): Promise<void | string>;\n",
    "\n",
    "  selectExamples(input_variables: Example): Promise<Example[]>;\n",
    "}\n",
    "```\n",
    "\n",
    "The only method it needs to define is a `selectExamples` method. This takes in the input variables and then returns a list of examples. It is up to each specific implementation as to how those examples are selected.\n",
    "\n",
    "LangChain has a few different types of example selectors. For an overview of all these types, see the below table.\n",
    "\n",
    "In this guide, we will walk through creating a custom example selector."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "638e9039",
   "metadata": {},
   "source": [
    "## Examples\n",
    "\n",
    "In order to use an example selector, we need to create a list of examples. These should generally be example inputs and outputs. For this demo purpose, let's imagine we are selecting examples of how to translate English to Italian."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "48658d53",
   "metadata": {},
   "outputs": [],
   "source": [
    "const examples = [\n",
    "    { input: \"hi\", output: \"ciao\" },\n",
    "    { input: \"bye\", output: \"arrivaderci\" },\n",
    "    { input: \"soccer\", output: \"calcio\" },\n",
    "];"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2830b49",
   "metadata": {},
   "source": [
    "## Custom Example Selector\n",
    "\n",
    "Let's write an example selector that chooses what example to pick based on the length of the word."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "56b740a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "import { BaseExampleSelector } from \"@langchain/core/example_selectors\";\n",
    "import { Example } from \"@langchain/core/prompts\";\n",
    "\n",
    "\n",
    "class CustomExampleSelector extends BaseExampleSelector {\n",
    "    private examples: Example[];\n",
    "  \n",
    "    constructor(examples: Example[]) {\n",
    "      super();\n",
    "      this.examples = examples;\n",
    "    }\n",
    "  \n",
    "    async addExample(example: Example): Promise<void | string> {\n",
    "      this.examples.push(example);\n",
    "      return;\n",
    "    }\n",
    "  \n",
    "    async selectExamples(inputVariables: Example): Promise<Example[]> {\n",
    "      // This assumes knowledge that part of the input will be a 'text' key\n",
    "      const newWord = inputVariables.input;\n",
    "      const newWordLength = newWord.length;\n",
    "  \n",
    "      // Initialize variables to store the best match and its length difference\n",
    "      let bestMatch: Example | null = null;\n",
    "      let smallestDiff = Infinity;\n",
    "  \n",
    "      // Iterate through each example\n",
    "      for (const example of this.examples) {\n",
    "        // Calculate the length difference with the first word of the example\n",
    "        const currentDiff = Math.abs(example.input.length - newWordLength);\n",
    "  \n",
    "        // Update the best match if the current one is closer in length\n",
    "        if (currentDiff < smallestDiff) {\n",
    "          smallestDiff = currentDiff;\n",
    "          bestMatch = example;\n",
    "        }\n",
    "      }\n",
    "  \n",
    "      return bestMatch ? [bestMatch] : [];\n",
    "    }\n",
    "  }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "ce928187",
   "metadata": {},
   "outputs": [],
   "source": [
    "const exampleSelector = new CustomExampleSelector(examples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "37ef3149",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ { input: \u001b[32m\"bye\"\u001b[39m, output: \u001b[32m\"arrivaderci\"\u001b[39m } ]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "await exampleSelector.selectExamples({ input: \"okay\" })"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "c5ad9f35",
   "metadata": {},
   "outputs": [],
   "source": [
    "await exampleSelector.addExample({ input: \"hand\", output: \"mano\" })"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e4127fe0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ { input: \u001b[32m\"hand\"\u001b[39m, output: \u001b[32m\"mano\"\u001b[39m } ]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "await exampleSelector.selectExamples({ input: \"okay\" })"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "786c920c",
   "metadata": {},
   "source": [
    "## Use in a Prompt\n",
    "\n",
    "We can now use this example selector in a prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "619090e2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import { PromptTemplate, FewShotPromptTemplate } from \"@langchain/core/prompts\"\n",
    "\n",
    "const examplePrompt = PromptTemplate.fromTemplate(\"Input: {input} -> Output: {output}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5934c415",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Translate the following words from English to Italain:\n",
      "\n",
      "Input: hand -> Output: mano\n",
      "\n",
      "Input: word -> Output:\n"
     ]
    }
   ],
   "source": [
    "const prompt = new FewShotPromptTemplate({\n",
    "    exampleSelector,\n",
    "    examplePrompt,\n",
    "    suffix: \"Input: {input} -> Output:\",\n",
    "    prefix: \"Translate the following words from English to Italain:\",\n",
    "    inputVariables: [\"input\"],\n",
    "})\n",
    "\n",
    "console.log(await prompt.format({ input: \"word\" }))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e767f69d",
   "metadata": {},
   "source": [
    "## Example Selector Types\n",
    "\n",
    "| Name       | Description                                                                                 |\n",
    "|------------|---------------------------------------------------------------------------------------------|\n",
    "| Similarity | Uses semantic similarity between inputs and examples to decide which examples to choose.    |\n",
    "| Length     | Selects examples based on how many can fit within a certain length                          |\n",
    "\n",
    "## Next steps\n",
    "\n",
    "You've now learned a bit about using example selectors to few shot LLMs.\n",
    "\n",
    "Next, check out some guides on some other techniques for selecting examples:\n",
    "\n",
    "- [How to select examples by length](/docs/how_to/example_selectors_length_based)\n",
    "- [How to select examples by similarity](/docs/how_to/example_selectors_similarity)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Deno",
   "language": "typescript",
   "name": "deno"
  },
  "language_info": {
   "file_extension": ".ts",
   "mimetype": "text/x.typescript",
   "name": "typescript",
   "nb_converter": "script",
   "pygments_lexer": "typescript",
   "version": "5.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
